home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / dskut / unshar.zip / UNSHAR.C < prev    next >
C/C++ Source or Header  |  1990-02-25  |  9KB  |  371 lines

  1. #include <stdio.h>
  2. #include "unshar.h"
  3.  
  4. /*
  5.  * Unshar - extract files from shell archive
  6.  *
  7.  * Written by Warren Toomey. Nov, 1989.
  8.  * You may freely copy or give away this source as
  9.  * long as this notice remains intact.
  10.  *
  11.  * Feb 1990--Fred C. Smith--Added make_subdir() which
  12.  * handles shar files which require extracted files to
  13.  * be inserted into a non-existent sub directory.
  14.  *
  15.  * Feb 1990--Fred C. Smith--Added APPEND mode in which unshar
  16.  * checks for existence of a file before unsharing, and if
  17.  * already exists it appends to it. Also outputs a message
  18.  * for each file indicating whether it is creating or
  19.  * appending (message is output in all modes).
  20.  */
  21.  
  22. /* Global variables */
  23.  
  24. int table;            /* Generate a table, or extract */
  25. int verbose;            /* Unshar verbosely - debugging */
  26. int numext;            /* Number of files to extract */
  27. char *exfile[100];        /* Files to extract */
  28.  
  29.  
  30. #define getline(x,y)    fgetline(stdin,x,y)
  31.  
  32. int fgetline(zin,how,buf)    /* Get a line from a file */
  33.  FILE *zin;
  34.  int how;            /* Ignore leading whitespace if */
  35.  char *buf;            /* how == NOWHITE */
  36.  {
  37.   int ch=NULL;
  38.  
  39.   *buf=NULL;            /* Null the buffer */
  40.   if (how==NOWHITE)        /* If skip any whitespace */
  41.     {
  42.      while (((ch=fgetc(zin))==' ') || (ch=='\t'));
  43.      if (ch==EOF)  return(EOF);    /* Returning EOF or NULL */
  44.      if (ch=='\n') return(NULL);
  45.      *buf++ =ch;        /* Put char in buffer */
  46.     }
  47.  
  48.   while ((ch=fgetc(zin))!='\n')    /* Now get the line */
  49.    {
  50.     if (ch==EOF) { *buf=NULL; return(EOF); }
  51.     *buf++ = ch;
  52.    }
  53.   
  54.   *buf=NULL;            /* Finally null-terminate the buffer */
  55.   return(NULL);            /* and return */
  56.  }
  57.  
  58.  
  59.  
  60. char *getstring(buf)        /* Get the next string from the buffer */
  61.  char *buf;            /* ignoring any quotes */
  62.  {
  63.   char out[BUFSIZE];
  64.   char *temp=out;
  65.   while ((*buf==' ') || (*buf=='\t')) buf++;    /* Skip whitespace */
  66.  
  67.   switch(*buf)            /* Now check first char */
  68.    {
  69.     case '\'' : buf++;
  70.         while (*buf!='\'') *temp++ = *buf++;
  71.         *temp=NULL;
  72.         return(out);
  73.     case '\"' : buf++;
  74.         while (*buf!='\"') *temp++ = *buf++;
  75.         *temp=NULL;
  76.         return(out);
  77.     case NULL : return(NULL);
  78.     default   : while ((*buf!=' ') && (*buf!='\t'))
  79.            if (*buf!='\\') *temp++ = *buf++;
  80.            else buf++;
  81.         *temp=NULL;
  82.         return(out);
  83.    }
  84.  }
  85.  
  86.  
  87. int firstword(buf)        /* Return token value of first word */
  88.  char *buf;            /* in the buffer. Assume no leading */
  89.  {                /* whitespace in the buffer */
  90.   int i;
  91.  
  92.   for (i=1;i<NUMTOKS;i++)
  93.      if (strncmp(buf,token[i],strlen(token[i]))==0)
  94.     return(i);
  95.  
  96.   return(UNKNOWN);
  97.  }
  98.  
  99.  
  100. int mustget(s1)            /* Return 1 if s1 is in the list of  */
  101.  char *s1;            /* files to extract. Return 0 if not */
  102.  {                
  103.   int i;
  104.  
  105.   if (numext==0) return(0);
  106.   for (i=0;i<numext;i++)
  107.    if (!strcmp(s1,exfile[i])) return(1);
  108.   return(0);
  109.  }
  110.  
  111. int make_subdir (fullpath)
  112.     char *fullpath;
  113.     {
  114.     char localpath [256];
  115.     int index;
  116.  
  117.     index = 0;
  118.     if (fullpath[1] == ':')
  119.         {
  120.         localpath[0] = fullpath[0];
  121.         localpath[1] = fullpath[1];
  122.         if (fullpath[2] == '\\' || fullpath[2] == '/')
  123.             localpath[2] = fullpath[2];
  124.         localpath[3] = (char) 0;
  125.         index = 3;
  126.         }
  127.     else if (fullpath[0]== '\\' || fullpath[0] == '/')
  128.         {
  129.         localpath[0] = fullpath[0];
  130.         localpath[1] = (char) 0;
  131.         index = 2;
  132.         }
  133.     for ( ; index < strlen (fullpath) ; index++)
  134.         {
  135.         if (fullpath[index] == '\\' || fullpath[index] == '/')
  136.             {
  137.             /* the stuff in localpath should be a full pathname of
  138.                 a subdirectory which might need to be made. check
  139.                 it, and if so, make it.
  140.              */
  141.             localpath[index] = (char) 0;
  142.             if (access (localpath, 0) == -1)    /* i.e., does not exist */
  143.                 {
  144.                 if (mkdir (localpath) == -1)
  145.                     return (-1);    /* mkdir failed */
  146.                 }
  147.             }
  148.         localpath[index] = fullpath[index];
  149.         }
  150.     return (0);
  151.     }
  152.  
  153.  
  154. void extract(how,file,end,lead, method)    /* Extract file, up until end word */
  155.  int how;            /* If how==YESX, then ignore lead   */
  156.  char *file;            /* character on every line */
  157.  char *end;
  158.  int lead;
  159.  int method;
  160.  {
  161.   FILE *zout;
  162.   char line[BUFSIZE];
  163.   char *temp, *openmode;
  164.   int ch;
  165.  
  166.   if (make_subdir(file) != 0)  /* make subdirs as required for file */
  167.     {
  168.     fprintf (stderr, "Cannot create subdirectory for %s\n", file);
  169.     return;
  170.     }
  171.  
  172.   if (method == APPEND)
  173.     {
  174.     if (access (file, 02) == 0)
  175.         {
  176.         openmode = "a";
  177.         printf (" (appending)\n");
  178.         }
  179.     else
  180.         {
  181.         openmode = "w";
  182.         printf (" (creating)\n");
  183.         }
  184.     }
  185.   else
  186.     {
  187.     openmode = "w";
  188.     printf (" (creating)\n");
  189.     }
  190.  
  191.   zout=fopen(file,openmode);        /* Open output file */
  192.   if (zout == NULL)
  193.     {
  194.     fprintf (stderr, "Cannot open file %s: Enter new name or <ENTER> to skip: ",
  195.             file);
  196.     gets (line);
  197.     if (line[0] != '\0')
  198.         {
  199.         zout = fopen (line, openmode);
  200.         if (zout==NULL)
  201.             { perror("unshar");
  202.               return;
  203.             }
  204.         }
  205.     }
  206.  
  207.   while(1)
  208.    {
  209.     ch=getline(WHITE,line);    /* Get a line of file */
  210.     temp=line;
  211.     if (ch==EOF)
  212.       { fprintf(zout,"%s\n",line);
  213.     fclose(zout);
  214.     return;
  215.       }
  216.  
  217.     if (strncmp(line,end,strlen(end))==0)    /* If end word */
  218.       { fclose(zout);                /* close the file */
  219.     return;
  220.       }
  221.  
  222.      if ((how==YESX) && (*temp==lead)) temp++;    /* Skip any lead */
  223.      fprintf(zout,"%s\n",temp);
  224.     }
  225.  }
  226.  
  227.  
  228. void getnames(buf,file,word)    /* Get the file & end word */
  229.  char *buf, *file, *word;    /* from the buffer */
  230.  {
  231.   char *temp;
  232.  
  233.   temp=buf;
  234.   if (verbose) printf("Getnames: buf is %s\n",buf);
  235.  
  236.   while (*temp!=NULL)        /* Scan along buffer */
  237.    {
  238.     switch(*temp)        /* Get file or end word */
  239.      {
  240.       case '>' : strcpy(file,getstring(++temp)); /* Get the file name */
  241.           break;
  242.       case '<' : if (*(++temp)=='<') ++temp;    /* Skip 2nd < */
  243.          strcpy(word,getstring(temp));    /* Get next word */
  244.          break;
  245.       default  : temp++;
  246.      }
  247.    }
  248.  }
  249.  
  250.  
  251.  
  252. void disembowel(method)        /* Unshar brutally! */
  253.   int method;
  254.  {
  255.   char buf[BUFSIZE];        /* Line buffer */
  256.   char file[BUFSIZE];        /* File name */
  257.   char word[BUFSIZE];        /* Word buffer */
  258.   int ch,x;
  259.  
  260.   if (verbose) printf("Entering disembowel\n");
  261.   x='X';            /* Leading X character */
  262.   while(1)
  263.    {
  264.     ch=getline(NOWHITE,buf);    /* Get a line from file */
  265.     if (ch==EOF) 
  266.     return;
  267.  
  268.     switch(firstword(buf))    /* Extract, depending on first word */
  269.      {
  270.       case CAT:
  271.       case GRES:
  272.       case SED:  if (verbose) printf("About to do getnames\n");
  273.          getnames(buf,file,word);
  274.          if (table==0)
  275.           {
  276.            if ((numext==0) || (mustget(file)))
  277.             {
  278.              printf("unshar: Extracting  %s",file);
  279.              if (verbose) 
  280.             printf("        stopping at %s\n",word);
  281.              extract(YESX,file,word,x,method);
  282.             }
  283.           }
  284.          else printf("%s\n",file);
  285.          break;
  286.       default:   break;
  287.      }
  288.    }
  289.  }
  290.   
  291.  
  292.  
  293. usage()
  294.  {
  295.   fprintf(stderr,"Usage: unshar [-t] [-b] [-v] [-xfile] [file(s)]\n");
  296.   exit(0);
  297.  }
  298.  
  299.  
  300. main(argc,argv)
  301.  int argc;
  302.  char *argv[];
  303.  {
  304.   extern int optind;
  305.   extern char *optarg;
  306.   int i,c,first;
  307.  
  308.   FILE *zin;            /* Dummy file descriptor */
  309.   int method;            /* Method of unsharing */
  310.  
  311.   method= APPEND;        /* default used to be BRUTAL */
  312.   table=  0;            /* Don't generate a table */
  313.   verbose=0;            /* Nor be very verbose */
  314.   numext= 0;            /* Initially no files to extract */
  315.  
  316.  
  317.   while ((c=getopt(argc,argv,"x:tbav"))!=EOF)
  318.     switch(c)
  319.      {
  320.       case 't' : table=1;    /* Get the various options */
  321.          break;
  322.       case 'a' : method= APPEND;
  323.          break;
  324.       case 'b' : method= BRUTAL;
  325.          break;
  326.       case 'v' : verbose=1;
  327.          break;
  328.       case 'x' : exfile[numext]= (char *)malloc(strlen(optarg)+1);
  329.          strcpy(exfile[numext++],optarg);
  330.          break;
  331.       default  : usage();
  332.      }
  333.  
  334.   if (argc==1) first=argc;        /* Find first file argument */
  335.   else for (first=1;first<argc;first++)
  336.     if (argv[first][0]!='-') break;
  337.  
  338.   if (first==argc)            /* If no file argument */
  339.    {                    /* use stdin only */
  340.     switch(method)
  341.      {
  342.       case APPEND: disembowel(method );    /* Unshar somewhat less brutally! */
  343.            break;
  344.       case BRUTAL: disembowel(method);    /* Unshar brutally! */
  345.            break;
  346.       default:       fprintf(stderr,"unshar: Unknown method